﻿using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

namespace MiHoMiao.Mono.UGUI.Triggers
{
    /// <summary>
    ///     使用鼠标拖动该对象时触发事件
    /// </summary>
    public class TriggerDragging : UIBehaviour, ITrigger, IPointerDownHandler
    {
        public enum DragType : byte
        {
            Horizontal,
            Vertical
        }

        [SerializeField] private UnityEvent m_OnTrigger = new UnityEvent();

        /// <summary>
        ///     拖动的方向
        /// </summary>
        public DragType DraggableType;

        /// <summary>
        ///     在指定方向上拖动的距离达到屏幕的一定百分时,
        ///     触发事件
        /// </summary>
        [Range(-1, 1)] public float DragLengthInScreenRate = 0.2f;

        public void OnPointerDown(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left) return;

            float dragDistance =
                DragLengthInScreenRate
                * (DraggableType is DragType.Horizontal
                    ? Screen.width
                    : Screen.height
                );

            float target = DraggableType is DragType.Horizontal
                ? eventData.position.x + dragDistance
                : eventData.position.y + dragDistance;

            if (DraggableType is DragType.Horizontal) FollowMouseHorizontal().Forget();
            else if (DraggableType is DragType.Vertical) FollowMouseVertical().Forget();
            return;

            async UniTaskVoid FollowMouseHorizontal()
            {
                while (Input.GetMouseButton(0))
                {
                    await UniTask.NextFrame();
                    if (dragDistance > 0 != Input.mousePosition.x > target) continue;
                    m_OnTrigger.Invoke();
                    return;
                }
            }

            async UniTaskVoid FollowMouseVertical()
            {
                while (Input.GetMouseButton(0))
                {
                    await UniTask.NextFrame();
                    if (dragDistance > 0 != Input.mousePosition.y > target) continue;
                    m_OnTrigger.Invoke();
                    return;
                }
            }
        }

        public UnityEvent OnTrigger
        {
            get => m_OnTrigger;
            set => m_OnTrigger = value;
        }
    }
}